package com.redstar.interesting.common.starter.filter;

import com.redstar.interesting.common.constants.Constants;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.UUID;


/**
 * dubbo服务消费者方的过滤器，把MDC的traceId透传到服务提供方
 * @author lihongxing
 */
@Activate(group = {CommonConstants.CONSUMER})
public class DubboConsumerTraceIdFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(DubboConsumerTraceIdFilter.class);


    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        boolean setTraceId = setTraceId(invocation);
        long startTime = System.currentTimeMillis();
        try{
            logger.info("Dubbo consumer request start URL path = {},methodName = {}",
                    invocation.getInvoker().getUrl(),invocation.getMethodName());
            return invoker.invoke(invocation);
        }finally {
            logger.info("Dubbo consumer request end URL path = {},methodName = {},time = {}ms",
                    invocation.getInvoker().getUrl(), invocation.getMethodName(), System.currentTimeMillis() - startTime);
            if (setTraceId) {
                MDC.clear();
            }
        }
    }

    private boolean setTraceId(Invocation invocation) {
        boolean newTraceId = false;
        //首先判断是否有traceId，如果没有则生成一个
        String traceId = invocation.getAttachment(Constants.TRACE_ID);
        if (StringUtils.isBlank(traceId)) {
            traceId = UUID.randomUUID().toString().replace("-", "");
            MDC.put(Constants.TRACE_ID, traceId);
            newTraceId = true;
        }
        //将生成的traceId 传递到服务的调用方
        invocation.getAttachments().put(Constants.TRACE_ID, traceId);
        return newTraceId;
    }


}
